package co.edu.usbcali.museo.presentation.backEndBeans;

import co.edu.usbcali.museo.exceptions.ExceptionMessages;
import co.edu.usbcali.museo.modelo.Autor;
import co.edu.usbcali.museo.modelo.Cuadro;
import co.edu.usbcali.museo.modelo.Museo;
import co.edu.usbcali.museo.modelo.Periodo;
import co.edu.usbcali.museo.modelo.Restauracion;
import co.edu.usbcali.museo.modelo.Sesion;
import co.edu.usbcali.museo.modelo.Tecnica;
import co.edu.usbcali.museo.modelo.Tipoestado;
import co.edu.usbcali.museo.modelo.control.AutorLogic;
import co.edu.usbcali.museo.modelo.control.CuadroLogic;
import co.edu.usbcali.museo.modelo.control.IAutorLogic;
import co.edu.usbcali.museo.modelo.control.ICuadroLogic;
import co.edu.usbcali.museo.modelo.control.IMuseoLogic;
import co.edu.usbcali.museo.modelo.control.IPeriodoLogic;
import co.edu.usbcali.museo.modelo.control.IRestauracionLogic;
import co.edu.usbcali.museo.modelo.control.ISesionLogic;
import co.edu.usbcali.museo.modelo.control.ITecnicaLogic;
import co.edu.usbcali.museo.modelo.control.ITipoestadoLogic;
import co.edu.usbcali.museo.modelo.control.MuseoLogic;
import co.edu.usbcali.museo.modelo.control.PeriodoLogic;
import co.edu.usbcali.museo.modelo.control.RestauracionLogic;
import co.edu.usbcali.museo.modelo.control.SesionLogic;
import co.edu.usbcali.museo.modelo.control.TecnicaLogic;
import co.edu.usbcali.museo.modelo.control.TipoestadoLogic;
import co.edu.usbcali.museo.modelo.dto.TecnicaDTO;
import co.edu.usbcali.museo.presentation.businessDelegate.BusinessDelegatorView;
import co.edu.usbcali.museo.utilities.DataPage;
import co.edu.usbcali.museo.utilities.DataSource;
import co.edu.usbcali.museo.utilities.PagedListDataModel;
import co.edu.usbcali.museo.utilities.Utilities;

import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.component.ext.HtmlCommandButton;
import com.icesoft.faces.component.ext.HtmlInputText;
import com.icesoft.faces.component.selectinputdate.SelectInputDate;
import com.icesoft.faces.context.DisposableBean;
import com.icesoft.faces.webapp.xmlhttp.FatalRenderingException;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;
import com.icesoft.faces.webapp.xmlhttp.TransientRenderingException;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;


/**
 *
 * @author Zathura Code Generator http://code.google.com/p/zathura,
 *
 */
public class TecnicaView extends DataSource implements Renderable,
DisposableBean {
	private HtmlInputText txtNombretecnica;
	private HtmlInputText txtCodtecnica;
	private HtmlCommandButton btnSave;
	private HtmlCommandButton btnModify;
	private HtmlCommandButton btnDelete;
	private HtmlCommandButton btnClear;
	private boolean renderDataTable;
	private boolean flag = true;
	private RenderManager renderManager;
	private PersistentFacesState state = PersistentFacesState.getInstance();
	private List<Tecnica> tecnica;
	private List<TecnicaDTO> tecnicaDTO;

	public TecnicaView() {
		super("");
	}

	public String action_clear() {
		txtNombretecnica.setValue(null);
		txtNombretecnica.setDisabled(true);
		txtCodtecnica.setValue(null);
		txtCodtecnica.setDisabled(false);
		btnSave.setDisabled(true);
		btnDelete.setDisabled(true);
		btnModify.setDisabled(true);
		btnClear.setDisabled(false);

		return "";
	}

	public void listener_txtId(ValueChangeEvent event) {
		if ((event.getNewValue() != null) && !event.getNewValue().equals("")) {
			Tecnica entity = null;

			try {
				Long codtecnica = new Long(txtCodtecnica.getValue().toString());
				entity = BusinessDelegatorView.getTecnica(codtecnica);
			} catch (Exception e) {
				// TODO: handle exception
			}

			if (entity == null) {
				txtNombretecnica.setDisabled(false);
				txtCodtecnica.setDisabled(false);
				btnSave.setDisabled(false);
				btnDelete.setDisabled(true);
				btnModify.setDisabled(true);
				btnClear.setDisabled(false);
			} else {
				txtNombretecnica.setValue(entity.getNombretecnica());
				txtNombretecnica.setDisabled(false);
				txtCodtecnica.setValue(entity.getCodtecnica());
				txtCodtecnica.setDisabled(true);
				btnSave.setDisabled(true);
				btnDelete.setDisabled(false);
				btnModify.setDisabled(false);
				btnClear.setDisabled(false);
			}
		}
	}

	public String action_save() {
		try {
			String codigoTecnica = txtCodtecnica.getValue().toString();
			String nombreTecnica= txtNombretecnica.getValue().toString();

			if(codigoTecnica == null || codigoTecnica.equals("")){
				throw new Exception("El c�digo de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloNumeros(codigoTecnica)==false){
				throw new Exception("El c�digo de la t�cnica no puede contener letras ni car�cteres especiales");
			}

			if(nombreTecnica== null || nombreTecnica.equals("")){
				throw new Exception("El nombre de la t�cnica es de car�cter obligatorio");
			}


			if(Utilities.soloLetras(nombreTecnica)==false){
				throw new Exception("El nombre de la t�cnica no permite n�meros ni car�cteres especiales");
			}

			BusinessDelegatorView.saveTecnica(new Long(codigoTecnica), nombreTecnica);

			FacesContext.getCurrentInstance().addMessage("", new FacesMessage("Se ha creado la t�cnica con �xito"));
			action_clear();
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}
		return "";
	}

	public String action_delete() {
		try {
			String codigoTecnica = txtCodtecnica.getValue().toString();

			if(codigoTecnica == null || codigoTecnica.equals("")){
				throw new Exception("El c�digo de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloNumeros(codigoTecnica)==false){
				throw new Exception("El c�digo de la t�cnica no puede contener letras ni car�cteres especiales");
			}

			BusinessDelegatorView.deleteTecnica(new Long(codigoTecnica));

			FacesContext.getCurrentInstance().addMessage("", new FacesMessage("Se ha eliminado la t�cnica con �xito"));
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		action_clear();

		return "";
	}


	public String action_modify() {
		try {
			String codigoTecnica = txtCodtecnica.getValue().toString();
			String nombreTecnica= txtNombretecnica.getValue().toString();

			if(codigoTecnica == null || codigoTecnica.equals("")){
				throw new Exception("El c�digo de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloNumeros(codigoTecnica)==false){
				throw new Exception("El c�digo la t�cnica no puede contener letras ni car�cteres especiales");
			}

			if(nombreTecnica== null || nombreTecnica.equals("")){
				throw new Exception("El nombre de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloLetras(nombreTecnica)==false){
				throw new Exception("El nombre de la t�cnica no permite n�meros ni car�cteres especiales");
			}
			
			BusinessDelegatorView.updateTecnica(new Long(codigoTecnica), nombreTecnica);
			FacesContext.getCurrentInstance().addMessage("", new FacesMessage("Se ha modificado la t�cnica con �xito"));
			action_clear();
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		return "";
	}

	public String action_modifyWitDTO(Long codtecnica, String nombretecnica)
	throws Exception {
		try {
			BusinessDelegatorView.updateTecnica(codtecnica, nombretecnica);
			renderManager.getOnDemandRenderer("TecnicaView").requestRender();
			FacesContext.getCurrentInstance()
			.addMessage("",
					new FacesMessage(ExceptionMessages.ENTITY_SUCCESFULLYMODIFIED));
		} catch (Exception e) {
			//renderManager.getOnDemandRenderer("TecnicaView").requestRender();
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
			throw e;
		}

		return "";
	}

	public List<Tecnica> getTecnica() {
		if (flag) {
			try {
				tecnica = BusinessDelegatorView.getTecnica();
				flag = false;
			} catch (Exception e) {
				flag = true;
				FacesContext.getCurrentInstance()
				.addMessage("", new FacesMessage(e.getMessage()));
			}
		}

		return tecnica;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setTecnica(List<Tecnica> tecnica) {
		this.tecnica = tecnica;
	}

	public boolean isRenderDataTable() {
		try {
			if (flag) {
				if (BusinessDelegatorView.findTotalNumberTecnica() > 0) {
					renderDataTable = true;
				} else {
					renderDataTable = false;
				}
			}

			flag = false;
		} catch (Exception e) {
			renderDataTable = false;
			e.printStackTrace();
		}

		return renderDataTable;
	}

	public DataModel getData() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModel(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and
	 * returned as a list of objects for display in the UI.
	 */
	private DataPage<Tecnica> getDataPage(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database.  This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberTecnica = 0;

		try {
			totalNumberTecnica = BusinessDelegatorView.findTotalNumberTecnica()
			.intValue();
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberTecnica) {
			endIndex = totalNumberTecnica;
		}

		try {
			tecnica = BusinessDelegatorView.findPageTecnica(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			// Remove this Renderable from the existing render groups.
			//leaveRenderGroups();        			
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		// Add this Renderable to the new render groups.
		//joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate JPA.  If the EntityManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with TopLink JPA, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		//EntityManagerHelper.getEntityManager().clear();
		flag = true;

		return new DataPage<Tecnica>(totalNumberTecnica, startRow, tecnica);
	}

	public DataModel getDataDTO() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModelDTO(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and
	 * returned as a list of objects for display in the UI.
	 */
	private DataPage<TecnicaDTO> getDataPageDTO(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database.  This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberTecnica = 0;

		try {
			totalNumberTecnica = BusinessDelegatorView.findTotalNumberTecnica()
			.intValue();
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberTecnica) {
			endIndex = totalNumberTecnica;
		}

		try {
			tecnica = BusinessDelegatorView.findPageTecnica(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			if (Utilities.validationsList(tecnica)) {
				tecnicaDTO = new ArrayList<TecnicaDTO>();

				for (Tecnica tecnicaTmp : tecnica) {
					TecnicaDTO tecnicaDTO2 = new TecnicaDTO();
					tecnicaDTO2.setCodtecnica(tecnicaTmp.getCodtecnica()
							.toString());
					tecnicaDTO2.setNombretecnica((tecnicaTmp.getNombretecnica() != null)
							? tecnicaTmp.getNombretecnica().toString() : null);
					tecnicaDTO2.setTecnica(tecnicaTmp);
					tecnicaDTO2.setTecnicaView(this);
					tecnicaDTO.add(tecnicaDTO2);
				}
			}

			// Remove this Renderable from the existing render groups.
			leaveRenderGroups();
		} catch (Exception e) {
			FacesContext.getCurrentInstance()
			.addMessage("", new FacesMessage(e.getMessage()));
		}

		// Add this Renderable to the new render groups.
		joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate JPA.  If the EntityManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with TopLink JPA, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		//EntityManagerHelper.getEntityManager().clear();
		flag = true;

		return new DataPage<TecnicaDTO>(totalNumberTecnica, startRow, tecnicaDTO);
	}

	protected boolean isDefaultAscending(String sortColumn) {
		return true;
	}

	/**
	 * This method is called when a render call is made from the server. Render
	 * calls are only made to views containing an updated record. The data is
	 * marked as dirty to trigger a fetch of the updated record from the
	 * database before rendering takes place.
	 */
	public PersistentFacesState getState() {
		onePageDataModel.setDirtyData();

		return state;
	}

	/**
	 * This method is called from faces-config.xml with each new session.
	 */
	public void setRenderManager(RenderManager renderManager) {
		this.renderManager = renderManager;
	}

	public void renderingException(RenderingException arg0) {
		if (arg0 instanceof TransientRenderingException) {
		} else if (arg0 instanceof FatalRenderingException) {
			// Remove from existing Customer render groups.
			leaveRenderGroups();
		}
	}

	/**
	 * Remove this Renderable from existing uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void leaveRenderGroups() {
		if (Utilities.validationsList(tecnicaDTO)) {
			for (TecnicaDTO tecnicaTmp : tecnicaDTO) {
				renderManager.getOnDemandRenderer("TecnicaView").remove(this);
			}
		}
	}

	/**
	 * Add this Renderable to the new uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void joinRenderGroups() {
		if (Utilities.validationsList(tecnicaDTO)) {
			for (TecnicaDTO tecnicaTmp : tecnicaDTO) {
				renderManager.getOnDemandRenderer("TecnicaView").add(this);
			}
		}
	}

	public void dispose() throws Exception {
	}

	public RenderManager getRenderManager() {
		return renderManager;
	}

	public void setState(PersistentFacesState state) {
		this.state = state;
	}

	public HtmlInputText getTxtNombretecnica() {
		return txtNombretecnica;
	}

	public void setTxtNombretecnica(HtmlInputText txtNombretecnica) {
		this.txtNombretecnica = txtNombretecnica;
	}

	public HtmlInputText getTxtCodtecnica() {
		return txtCodtecnica;
	}

	public void setTxtCodtecnica(HtmlInputText txtCodtecnica) {
		this.txtCodtecnica = txtCodtecnica;
	}

	public HtmlCommandButton getBtnSave() {
		return btnSave;
	}

	public void setBtnSave(HtmlCommandButton btnSave) {
		this.btnSave = btnSave;
	}

	public HtmlCommandButton getBtnModify() {
		return btnModify;
	}

	public void setBtnModify(HtmlCommandButton btnModify) {
		this.btnModify = btnModify;
	}

	public HtmlCommandButton getBtnDelete() {
		return btnDelete;
	}

	public void setBtnDelete(HtmlCommandButton btnDelete) {
		this.btnDelete = btnDelete;
	}

	public HtmlCommandButton getBtnClear() {
		return btnClear;
	}

	public void setBtnClear(HtmlCommandButton btnClear) {
		this.btnClear = btnClear;
	}

	public void setRenderDataTable(boolean renderDataTable) {
		this.renderDataTable = renderDataTable;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public List<TecnicaDTO> getTecnicaDTO() {
		return tecnicaDTO;
	}

	public void setTecnicaDTO(List<TecnicaDTO> tecnicaDTO) {
		this.tecnicaDTO = tecnicaDTO;
	}

	public TimeZone getTimeZone() {
		return java.util.TimeZone.getDefault();
	}

	/**
	 * A special type of JSF DataModel to allow a datatable and datapaginator
	 * to page through a large set of data without having to hold the entire
	 * set of data in memory at once.
	 * Any time a managed bean wants to avoid holding an entire dataset,
	 * the managed bean declares this inner class which extends PagedListDataModel
	 * and implements the fetchData method. fetchData is called
	 * as needed when the table requires data that isn't available in the
	 * current data page held by this object.
	 * This requires the managed bean (and in general the business
	 * method that the managed bean uses) to provide the data wrapped in
	 * a DataPage object that provides info on the full size of the dataset.
	 */
	private class LocalDataModel extends PagedListDataModel {
		public LocalDataModel(int pageSize) {
			super(pageSize);
		}

		public DataPage<Tecnica> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPage(startRow, pageSize);
		}
	}

	private class LocalDataModelDTO extends PagedListDataModel {
		public LocalDataModelDTO(int pageSize) {
			super(pageSize);
		}

		public DataPage<TecnicaDTO> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPageDTO(startRow, pageSize);
		}
	}
}
